package v.book.read.tip.polymorphicfactories;

import java.util.*;
import junit.framework.*;

interface Shape {
	void draw();

	void erase();
}

abstract class ShapeFactory {
	protected abstract Shape create();

	private static Map factories = new HashMap();

	public static void addFactory(String id, ShapeFactory f) {
		factories.put(id, f);
	}

	// A Template Method:
	public static final Shape createShape(String id) {
		if (!factories.containsKey(id)) {
			try {
				// Load dynamically
				Class.forName("factory.shapefact2." + id);
			} catch (ClassNotFoundException e) {
				throw new RuntimeException("Bad shape creation: " + id);
			}
			// See if it was put in:
			if (!factories.containsKey(id))
				throw new RuntimeException("Bad shape creation: " + id);
		}
		return ((ShapeFactory) factories.get(id)).create();
	}
}

class Circle implements Shape {
	private Circle() {
	}

	public void draw() {
		System.out.println("Circle.draw");
	}

	public void erase() {
		System.out.println("Circle.erase");
	}

	private static class Factory extends ShapeFactory {
		protected Shape create() {
			return new Circle();
		}
	}

	static {
		ShapeFactory.addFactory("Circle", new Factory());
	}
}

class Square implements Shape {
	private Square() {
	}

	public void draw() {
		System.out.println("Square.draw");
	}

	public void erase() {
		System.out.println("Square.erase");
	}

	private static class Factory extends ShapeFactory {
		protected Shape create() {
			return new Square();
		}
	}

	static {
		ShapeFactory.addFactory("Square", new Factory());
	}
}

public class ShapeFactory2 extends TestCase {
	String shlist[] = { "Circle", "Square", "Square", "Circle", "Circle",
			"Square" };
	List shapes = new ArrayList();

	public void test() {
		// This just makes sure it will complete
		// without throwing an exception.
		Iterator it = Arrays.asList(shlist).iterator();
		while (it.hasNext())
			shapes.add(ShapeFactory.createShape((String) it.next()));
		it = shapes.iterator();
		while (it.hasNext()) {
			Shape s = (Shape) it.next();
			s.draw();
			s.erase();
		}
	}

	public static void main(String args[]) {
		junit.textui.TestRunner.run(ShapeFactory2.class);
	}
} // /:~
